home *** CD-ROM | disk | FTP | other *** search
/ Atari Mega Archive 1 / Atari Mega Archive - Volume 1.iso / mint / utils / lack.zoo / fs.c < prev    next >
Encoding:
C/C++ Source or Header  |  1993-12-27  |  13.7 KB  |  660 lines

  1. /* contains all filesystem code, and everything related to processes and their
  2.  * environments
  3.  */
  4. #include "lack.h"
  5. #include "atarierr.h"
  6. #include "sysvars.h"
  7. #include <ostruct.h>
  8. #include <osbind.h>
  9. #include <mintbind.h>
  10. #include <string.h>
  11. #include <signal.h>
  12.  
  13. #define LA_DRV   18 /* s:\ */
  14.  
  15. #define ENVIRON_SIZE 1024
  16.  
  17. const struct kerinfo *kernal;
  18.  
  19. extern int apid;
  20. extern lap *lapps[NUM_APPS];
  21. extern lap *curapp;
  22. extern struct global_action *gl_action;
  23.  
  24. /* lacc.c: */
  25. int interface(BASEPAGE *);
  26. int empty_acc(BASEPAGE *);
  27.  
  28. struct thread
  29. {
  30.     long size;
  31.     char *name;
  32.     void *arg;
  33.     void (*func)();
  34. };
  35.  
  36. volatile struct thread *thread;
  37. long ts;
  38.  
  39. struct msg{ long msg1, msg2; short pid;};
  40.  
  41. int first=TRUE; /* is this the first lacc to call fscntl */
  42.  
  43. long
  44. init_acc(char *base)
  45. {
  46.     /* only once we know that gem is started can we catch trap 2 */
  47.     char tname[9];
  48.     ksyield;
  49.     kpsigblock;
  50.     kpsigsetmask;
  51.     kpmsg;
  52.     struct msg m;
  53.     lap *a;
  54.     lap *caller=curapp; /* This corresponds to the MiNT proccess, not the
  55.                  * current apid, which we do not know yet.
  56.                  */
  57.  
  58.     caller->mask=p_sigblock(-1);
  59.     while(thread) s_yield();
  60.     thread=(struct thread *)kmalloc(sizeof(*thread));
  61.     a=(lap *)kmalloc(sizeof(lap) + sizeof(struct lacc));
  62.     bzero(a, sizeof(lap) + sizeof(struct lacc));
  63.     a->acc=(struct lacc *)(a+1);
  64.     apid=cur_apid;
  65.     TRACE("lack: creating proc for apid %d", apid);
  66.     curapp=a;
  67.     lapps[apid]=a;
  68.     if(first)
  69.     {
  70.         first=FALSE;
  71.         thread->size=4096;
  72.         thread->name="lackontrol";
  73.         thread->func=interface;
  74.     }else{
  75.         thread->size=1024;
  76.         ksprintf(tname, "apid%d", cur_apid);
  77.         thread->name=tname;
  78.         thread->func=empty_acc;
  79.     }
  80.     thread->arg=a;
  81.     /* this whole business is extremely time critical, so we want to start
  82.      * it with a nice bug hunk of cpu slices.
  83.      */
  84.     s_yield();
  85.     wake(IO_Q, ts);
  86.     sleep(IO_Q, ts);
  87.     kfree(thread);
  88.     thread=NULL;
  89.     DEBUG("lack: going to sleep on %lx", caller);
  90.     p_msg(0, caller, &m);
  91.     /* Notice it waits for the value of lapps[apid], so that the main
  92.      * application and a non lack acc are sleeping on the same
  93.      * condition. apid starts at zero, and each time an acc starts, it
  94.      * updates it.  This process goes to sleep on the last known apid, then
  95.      * the new process starts and makes apid valid.
  96.      */
  97.     DEBUG("lack: who woke me? %lx", caller);
  98.     apid=cur_apid;
  99.     curapp=lapps[apid];
  100.     return((long)caller);
  101.                    /* right now, it is just to complicated to eliminate
  102.                     * the caller acc.  After leaving the kernal, I need to
  103.                     * longjump back into the caller pid's stack (is now in
  104.                     * the acc stack).
  105.                     */
  106. }
  107.  
  108. long
  109. kill_acc(int apid)
  110. {
  111.     struct global_action *k, *old;
  112.  
  113.     k=(struct global_action *)kmalloc(sizeof(*k));
  114.     k->type=GL_SEND_KILL;
  115.     k->apid=apid;
  116.     k->next=NULL;
  117.     if(old=gl_action)
  118.     {
  119.         while(old->next) old=old->next;
  120.         old->next=k;
  121.     }else
  122.         gl_action=k;
  123.     lapps[apid]->action=APPL_KILL;
  124.     return 0;
  125. }
  126.  
  127.  
  128. int
  129. make_proc(long stacksize, char *name, void *arg, void(*func)())
  130. {
  131.     kpexec;
  132.     kmshrink;
  133.     BASEPAGE *b;
  134.  
  135.     b=(BASEPAGE *)p_exec(PE_CBASEPAGE, NULL, "", NULL);
  136.     m_shrink(0, b, stacksize + 256);
  137.     b->p_tbase=(char *)func;
  138.     b->p_dbase=(char *)arg;
  139.     b->p_hitpa=((char *)b) + stacksize + 256;
  140.     return((int)p_exec(PE_ASYNC_GO, name, b, NULL));
  141. }
  142.  
  143. void
  144. ts_start(BASEPAGE *b)
  145. {
  146.     _setstack(b->p_hitpa);
  147.  
  148.     Syield();
  149.     if(Fsfirst("u:\\s", FA_DIR))
  150.     {
  151.         Cconws("Where is U:\\S???");
  152.         Pterm(-1);
  153.     }
  154.     Frename(0, "u:\\s", "u:\\.gem");
  155.     Pdomain(0);
  156.     Dcntl(LA_THREAD_SERVER, "S:", (long)b);
  157. }
  158.  
  159. char *
  160. make_name_tail(char *name_tail, const char *path)
  161. {
  162.     /* returns a pointer to the full filename in path, and fills name_tail
  163.      * with up to 8 uppercase characters of it, excluding the
  164.      * extension. blanks filled with ' '.
  165.      */
  166.     const char *where_tail, *dot;
  167.     int length;
  168.     
  169.     where_tail=strrchr(path, (int)'\\');
  170.     where_tail++;
  171.     dot=strchr(where_tail, (int)'.');
  172.     if(!dot) length=strlen(where_tail);
  173.     else length=dot - where_tail;
  174.     if(length>8) length=8;
  175.     strncpy(name_tail, where_tail, length);
  176.     strupr(name_tail);
  177.     if(length<8) memset(name_tail+length, 0x20, 8 - length);
  178.     return(where_tail);
  179. }
  180.  
  181. long
  182. launch_prg(char *name, char *args)
  183. {
  184.     long ssp;
  185.     char *name_tail, *acc_name=curapp->acc->name;
  186.  
  187.     ssp=Super(0);
  188.     DEBUG("start program: %s args: %s", name, args);
  189.     name_tail=make_name_tail(acc_name, name);
  190.     DEBUG("name tail %s, aes name %s", name_tail, acc_name);
  191.     strcpy(aes_appl->name, acc_name);
  192.     Menu_unregister();
  193.     Super(ssp);
  194.     return (Pexec(0, name, args, NULL));
  195. }
  196.  
  197. struct acc_base
  198. {
  199.     char *tbase; /* this is changed to set_a0() */
  200.     long tlen;   /* this is changed to the parent's domain */
  201.     char *dbase; /* this is changed to the acc_base structure holding
  202.               * the orignal values */
  203. };
  204.  
  205. acc_quit(long signal)
  206. {
  207. /* I should find the apid inside of fscntl, someday, I may get this thing to
  208.  * work with memprot.
  209.  */
  210.     int pid, apid;
  211.  
  212.     pid=Pgetpid();
  213.     for(apid=2; apid < NUM_APPS; apid++)
  214.         if(lapps[apid] && lapps[apid]->acc)
  215.             if(lapps[apid]->acc->pid==pid) break;
  216.     if(apid < NUM_APPS && lapps[apid])
  217.         Dcntl(LA_KILL_ACC, "S:", (long)apid);
  218. /* right now, we always return while our own aes application is active
  219.  */
  220. }
  221.  
  222. const static long clear_regs[14]={0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
  223.  
  224. void
  225. set_a0(BASEPAGE *b)
  226. {
  227.     struct acc_base *a;
  228.     
  229.     _setstack(b->p_hitpa);
  230.     curapp->acc->pid=Pgetpid();
  231.     curapp->acc->base=b;
  232.  
  233.     Pdomain((short)b->p_tlen);
  234.     Psignal(SIGUSR2, acc_quit);
  235.     Psignal(SIGINT, acc_quit);
  236.     a=(struct acc_base *)b->p_dbase;
  237.     b->p_tbase=a->tbase;
  238.     b->p_tlen =a->tlen;
  239.     b->p_dbase=a->dbase;
  240.     b->p_parent=NULL;
  241.     asm("    moval %0, a0;\
  242.         movl  a0, sp@-;\
  243.         movml _clear_regs, d0-d7/a1-a6;\
  244.         movl  a0@(8), sp@-;\
  245.         rts"::"r"(b));
  246.     Pterm(0);
  247. }
  248.  
  249. long
  250. launch_acc(char *name)
  251. {
  252.     kpexec;
  253.     kmshrink;
  254.     kpdomain;
  255.     kpwait;
  256.     BASEPAGE *b;
  257.     struct acc_base a;
  258.     long size, name_tail_len;
  259.     char *name_tail, *acc_name=curapp->acc->name;
  260. /*    char *moms_stack; there ought to be some way to start this without
  261.  * the extra 256 bytes for stack, maybe acc's mind this */
  262.     int dom;
  263.  
  264.     DEBUG("start acc %s", name);
  265.     dom=p_domain(-1);
  266.     b=(BASEPAGE *)p_exec(PE_LOAD, name, "", NULL);
  267.     if((long)b < 0 )
  268.     {
  269.         p_domain(dom==0 ? 1 : 0); /* try again for minixfs */
  270.         b=(BASEPAGE *)p_exec(PE_LOAD, name, "", NULL);
  271.         p_domain(dom);
  272.         if ((long)b < 0) return (long)b;
  273.     }
  274.     size=512 + b->p_tlen + b->p_dlen + b->p_blen;
  275.     /* oh dear, what if this is a shtext file? */
  276.     /* a wee bit of room for the stack */
  277.     b->p_hitpa=(char *)b + size;
  278.     m_shrink(0, b, size);
  279.     
  280.     /* now set the name for appl_find */
  281.     name_tail=make_name_tail(acc_name, name);
  282.     DEBUG("name tail %s, aes name %s", name_tail, acc_name);
  283.     strcpy(aes_appl->name, acc_name);
  284.     Menu_unregister();
  285.     
  286.     b->p_hitpa=(char *)b + size;
  287.     a.tbase=b->p_tbase;
  288.     a.tlen =b->p_tlen;
  289.     a.dbase=b->p_dbase;
  290.     b->p_tbase=(char *)set_a0;
  291.     b->p_tlen=dom;
  292.     b->p_dbase=(char *)&a;
  293.     
  294.     p_exec(106, name_tail, b, NULL);
  295.     return(p_wait());
  296. }
  297.  
  298.  
  299. char **
  300. build_env(char *from)
  301. /* this is the first half of mintlibs parseargs from crtinit.c.  If it ain't broke,
  302.  * don't fix it.  Written by eric r smith for the public domain.
  303.  */
  304. {
  305.     kMalloc;
  306.     kmshrink;
  307.     char **environ;
  308.     long count = 4;        /* compensate for aligning */
  309.     long  i;
  310.     char **more_env;    /* memory block to m_shrink */
  311.     char **envp;
  312.     char *null_list = 0;
  313. /* flag to indicate desktop-style arg. passing */
  314.     long desktoparg = 0;
  315.  
  316. /* handle the environment first */
  317.  
  318.     more_env = environ = envp = (char **)m_alloc(ENVIRON_SIZE);
  319.     while (*from) {
  320.         if(count>=ENVIRON_SIZE)
  321.         {
  322.             ALERT("lack: not enough room to build environ");
  323.             more_env=(char **)m_alloc(ENVIRON_SIZE);
  324.             if(more_env != envp)
  325.             {
  326.                 ALERT("lack: could not grow environ");
  327.                 break;
  328.             }
  329.             count=4;
  330.         }
  331.  
  332. /* if we find MWC arguments, tie off environment here */
  333.         if (*from == 'A' && *(from+1) == 'R' && *(from+2) == 'G' &&
  334.             *(from+3) == 'V' && *(from+4) == '=')
  335.                 break;
  336.         *envp++ = from;
  337.         count += 4;
  338.         desktoparg = 1;
  339.         while (*from) {
  340.             if (*from == '=') {
  341.                 desktoparg = 0;
  342.             }
  343.             from++;
  344.         }
  345.         from++;        /* skip 0 */
  346.  
  347. /* the desktop (and some shells) use the environment in the wrong
  348.    way, putting in "PATH=\0C:\0" instead of "PATH=C:". so if we
  349.    find an "environment variable" without an '=' in it, we
  350.    see if the last environment variable ended with '=\0', and
  351.    if so we append this one to the last one
  352.  */
  353.         if(desktoparg && envp > &environ[1]) 
  354.         {
  355.         /* launched from desktop -- fix up env */
  356.             char *p, *q;
  357.  
  358.             q = envp[-2];    /* current one is envp[-1] */
  359.             while (*q) q++;
  360.             if (q[-1] == '=') {
  361.             p = *--envp;
  362.             while(*p)
  363.                *q++ = *p++;
  364.                 *q = '\0';
  365.            }
  366.         }
  367.     }
  368.     *envp++ = (char *)0;
  369.     count += 4;
  370.     m_shrink(0, more_env, count);
  371.     return environ;
  372. }
  373.  
  374. extern int is_desk; /* temporarily used to choose debugging level */
  375.  
  376. long
  377. la_fscntl(fcookie *dir, char *name, int cmd, long arg)
  378. {
  379.     struct msg m;
  380.  
  381.     switch(cmd)
  382.     {
  383.         case LA_THREAD_SERVER:
  384.             ts=arg;
  385.             while(1)
  386.             {
  387.                 TRACE("lack: apid0 going to sleep on its own basepage %lx", arg);
  388.                 sleep(IO_Q, arg);
  389.                 make_proc(thread->size, thread->name, thread->arg, thread->func);
  390.                 wake(IO_Q, arg);
  391.             }
  392.         case LA_INIT_ACC:
  393.             if(!ts)
  394.             {
  395.                  ALERT("lack: can't find thread server apid0");
  396.                  return(-1);
  397.             }
  398.             DEBUG("lack: fscntl LA_INIT_ACC");
  399.             return (init_acc((char *)arg));
  400.         case LA_WAKE_APP:
  401.         {
  402.             kpmsg;
  403.             kpgetpid;
  404.             
  405.             if(is_desk) DEBUG("lack: fscntl LA_WAKE_APP %lx", arg);
  406.             else TRACE("lack: fscntl LA_WAKE_APP %lx", arg);
  407.             m.pid=p_getpid();
  408.             p_msg(1, arg, &m);
  409.             p_msg(0, curapp, &m);
  410.             return 0;
  411.         }
  412.         case LA_LOAD_ACC:
  413.             DEBUG("lack: fscntl LA_LOAD_ACC %s", arg);
  414.             return (launch_acc((char *)arg));
  415.         case LA_KILL_ACC:
  416.             DEBUG("lack: fscntl LA_KILL_ACC apid %ld", arg);
  417.             return (kill_acc((int)arg));
  418.         case LA_BUILD_ENV:
  419.             DEBUG("lack: fscntl LA_BUILD_ENV from environ at %lx", arg);
  420.             /* it would be nice to emulate shel commands using mintlibs environ
  421.              * functions.  First you have to find the caller's basepage */
  422.             return ((long)build_env((char *)arg));
  423.         default:
  424.             DEBUG("lack: fscntl %x(%lx) I don't know this one", cmd, arg);
  425.             return EINVFN;
  426.     }
  427. }
  428.  
  429. FILESYS lackfs; /* forward declaration */
  430.  
  431. long
  432. la_root(int drv, fcookie *fc)
  433. {
  434.     if(drv==LA_DRV)
  435.     {
  436.         fc->fs=&lackfs;
  437.         fc->dev=LA_DRV;
  438.         fc->index=0;
  439.         return 0;
  440.     }
  441.     return EDRIVE;
  442. }
  443.  
  444. long
  445. la_dupcookie(fcookie *dest, fcookie *src)
  446. {
  447.     *dest=*src;
  448.     return 0;
  449. }
  450.  
  451. long
  452. no_lookup(fcookie *dir, char *name, fcookie *entry)
  453. {
  454.     if(dir->index==0 && (name=="." || name=="" || !name))
  455.         la_dupcookie(entry, dir);
  456.     else
  457.         return EFILNF;
  458. }
  459.  
  460. long
  461. no_creat(fcookie *dir, char *name, unsigned mode, int attr, fcookie *entry)
  462. {
  463.     return EACCDN;
  464. }
  465.  
  466. DEVDRV *
  467. no_getdev(fcookie *file, long *special)
  468. {
  469.     *special=EINVFN;
  470.     return NULL;
  471. }
  472.  
  473. long
  474. no_getxattr(fcookie *file, XATTR *xattr)
  475. {
  476.     ktgettime;
  477.     ktgetdate;
  478.     
  479.     if(file->index==0)
  480.     {
  481.         xattr->mode=S_IFDIR | 0755;
  482.         xattr->index=0;
  483.         xattr->dev=LA_DRV;
  484.         xattr->uid=xattr->gid=xattr->size=0;
  485.         xattr->nlink=1;
  486.         xattr->mtime=t_gettime();
  487.         xattr->mdate=t_getdate();
  488.         xattr->attr=FA_DIR;
  489.         return 0;
  490.     }
  491.     return EACCDN;
  492. }
  493.  
  494. long
  495. no_chown(fcookie *file, int uid, int gid)
  496. {
  497.         return EINVFN;
  498. }
  499.  
  500. long
  501. no_chmode(fcookie *file, unsigned mode)
  502. {
  503.         return EINVFN;
  504. }
  505.  
  506.  
  507. long
  508. no_mkdir(fcookie *dir, char *name, unsigned mode)
  509. {
  510.     return EACCDN;
  511. }
  512.  
  513. long
  514. no_rmdir(fcookie *dir, char *name)
  515. {
  516.         return EACCDN;
  517. }
  518.  
  519. long
  520. no_remove(fcookie *dir, char *name)
  521. {
  522.     return EACCDN;
  523. }
  524.  
  525. long
  526. no_getname(fcookie *root,fcookie *dir, char *pathname, int length)
  527. {
  528.     return EACCDN;
  529. }
  530.  
  531.  
  532. long
  533. no_opendir(DIR *dirh, int flag)
  534. {
  535.     return 0;
  536. }
  537.  
  538. long
  539. no_readdir(DIR *dirh, char *name, int namelen, fcookie *fc)
  540. {
  541.         return ENMFIL;
  542. }
  543.  
  544. long
  545. no_rewinddir(DIR *dirh)
  546. {
  547.     return 0;
  548. }
  549.  
  550. long
  551. no_closedir(DIR *dirh)
  552. {
  553.     return 0;
  554. }
  555.  
  556. long
  557. no_rlabel(fcookie *dir, char *name, int namelen)
  558. {
  559.     return EFILNF;
  560. }
  561.  
  562. long
  563. no_wlabel(fcookie *dir, char *name)
  564. {
  565.     return EACCDN;
  566. }
  567.  
  568. long
  569. no_dfree(fcookie *dir, long *buffer)
  570. {
  571.     return EINVFN;
  572. }
  573.  
  574. long
  575. no_rename(fcookie *olddir, char *oldname, fcookie *newdir, char *newname)
  576. {
  577.         return EACCDN;
  578. }
  579.  
  580. long
  581. no_hardlink(fcookie *fromdir, char *fromname, fcookie *todir, char *toname)
  582. {
  583.         return EINVFN;
  584. }
  585.  
  586. long
  587. no_symlink(fcookie *dir, char *name, char *to)
  588. {
  589.         return EINVFN;
  590. }
  591.  
  592. long
  593. no_readlink(fcookie *file, char *buf, int len)
  594. {
  595.     return EINVFN;
  596. }
  597.  
  598. long
  599. no_chattr(fcookie *file, int attr)
  600. {
  601.     return EFILNF;
  602. }
  603.  
  604. long
  605. no_pathconf(fcookie *dir, int which)
  606. {
  607.     return EINVFN;
  608. }
  609.  
  610. long
  611. no_dskchng(int drv)
  612. {
  613.     return 0;
  614. }
  615.  
  616. long
  617. la_release(fcookie *fc)
  618. {
  619.     return 0;
  620. }
  621.  
  622. FILESYS lackfs={
  623.     NULL, 0,
  624.     la_root, no_lookup, no_creat, no_getdev,
  625.     no_getxattr, no_chattr, no_chown,
  626.     no_chmode, no_mkdir,
  627.     no_rmdir, no_remove, no_getname,
  628.     no_rename, no_opendir, no_readdir,
  629.     no_rewinddir, no_closedir,
  630.     no_pathconf, no_dfree,
  631.     no_wlabel, no_rlabel,
  632.     no_symlink, no_readlink,
  633.     no_hardlink, la_fscntl, no_dskchng,
  634.     la_release,la_dupcookie
  635. };
  636.  
  637. FILESYS *
  638. la_init(const struct kerinfo *k)
  639. {
  640.     kernal=k;
  641.     k->dos_tab[9]("lack: load ackessories\r\n");
  642.     k->dos_tab[9]("\tthere was suddenly this awful lack\r\n");
  643.     k->dos_tab[9]("\tthings had changed that's for sure\r\n");
  644.     k->dos_tab[9]("\t\t-NoMeansNo\r\n");
  645.     if(*_drvbit & (1L << LA_DRV))
  646.     {
  647.         ALERT("lack: drive %d already in use.", LA_DRV);
  648.         return NULL;
  649.     }
  650.     *_drvbit |= (1L << LA_DRV);
  651.     make_proc(512, "apid0", NULL, ts_start);
  652.     lapps[0]=(lap *)kmalloc(sizeof(lap));
  653.     bzero(lapps[0], sizeof(lap));
  654.     apid=0;
  655.     curapp=lapps[0];
  656.     return &lackfs;
  657. }
  658.  
  659.  
  660.